import os
import logging
import logging.handlers
import datetime
import threading

class ETCLogger:
    _instance = None
    _lock = threading.Lock()

    def __new__(cls, log_dir=None, roll_save_count=3, roll_save_status=True):
        with cls._lock:
            if not cls._instance:
                cls._instance = super().__new__(cls)
                cls._instance._init_logger(log_dir, roll_save_count, roll_save_status)
            return cls._instance

    def _init_logger(self, log_dir, roll_save_count, roll_save_status):
        if log_dir is None:
            log_dir = os.path.join(os.path.expanduser("~"), "Desktop")

        self.basedir = log_dir
        self.roll_save_count = roll_save_count
        self.roll_save_status = roll_save_status

        # 创建日志目录
        self.log_base_path = os.path.join(self.basedir, "ETC_D4510_Log")
        if not os.path.exists(self.log_base_path):
            os.makedirs(self.log_base_path)

        # 配置日志记录器
        self.logger = logging.getLogger(__name__)
        self.logger.setLevel(logging.DEBUG)

        # 定义日志格式
        formatter = logging.Formatter('[%(asctime)s] [%(filename)s-%(funcName)s %(lineno)d] %(message)s')

        # 创建控制台处理器
        console_handler = logging.StreamHandler()
        console_handler.setLevel(logging.DEBUG)
        console_handler.setFormatter(formatter)

        # 创建不同级别的日志处理器
        debug_handler = self._create_handler(os.path.join(self.log_base_path, "Debug"), logging.DEBUG, formatter)
        info_handler = self._create_handler(os.path.join(self.log_base_path, "Info"), logging.INFO, formatter)
        warning_handler = self._create_handler(os.path.join(self.log_base_path, "Warning"), logging.WARNING, formatter)
        error_handler = self._create_handler(os.path.join(self.log_base_path, "Error"), logging.ERROR, formatter)

        # 创建 All 文件夹的日志处理器
        all_handler = self._create_handler(os.path.join(self.log_base_path, "All"), logging.DEBUG, formatter)

        # 添加处理器到日志记录器
        self.logger.addHandler(console_handler)
        self.logger.addHandler(debug_handler)
        self.logger.addHandler(info_handler)
        self.logger.addHandler(warning_handler)
        self.logger.addHandler(error_handler)
        self.logger.addHandler(all_handler)

    def _create_handler(self, log_path, level, formatter):
        if not os.path.exists(log_path):
            os.makedirs(log_path)

        log_file = os.path.join(log_path, datetime.datetime.now().strftime("%Y-%m-%d") + ".log")
        handler = logging.FileHandler(log_file)
        handler.setLevel(level)
        handler.setFormatter(formatter)

        # 配置文件滚动机制
        if self.roll_save_status:
            file_roll_handler = logging.handlers.RotatingFileHandler(
                log_file, maxBytes=1024 * 1024, backupCount=self.roll_save_count
            )
            file_roll_handler.setLevel(level)
            file_roll_handler.setFormatter(formatter)
            return file_roll_handler
        return handler

    def info(self, message, isPrint=True):
        """
        记录 INFO 级别的日志
        :param message: 日志信息
        :param isPrint: 是否在终端打印日志
        """
        if isPrint:
            self.logger.info(message)
        else:
            # 仅记录到文件，不打印到终端
            for handler in self.logger.handlers:
                if isinstance(handler, logging.FileHandler) and ("Info" in handler.baseFilename or "All" in handler.baseFilename):
                    handler.emit(logging.LogRecord(
                        name=self.logger.name,
                        level=logging.INFO,
                        pathname=__file__,
                        lineno=0,
                        msg=message,
                        args=None,
                        exc_info=None
                    ))

    def debug(self, message, isPrint=True):
        """
        记录 DEBUG 级别的日志
        :param message: 日志信息
        :param isPrint: 是否在终端打印日志
        """
        if isPrint:
            self.logger.debug(message)
        else:
            # 仅记录到文件，不打印到终端
            for handler in self.logger.handlers:
                if isinstance(handler, logging.FileHandler) and ("Debug" in handler.baseFilename or "All" in handler.baseFilename):
                    handler.emit(logging.LogRecord(
                        name=self.logger.name,
                        level=logging.DEBUG,
                        pathname=__file__,
                        lineno=0,
                        msg=message,
                        args=None,
                        exc_info=None
                    ))

    def error(self, message, isPrint=True):
        """
        记录 ERROR 级别的日志
        :param message: 日志信息
        :param isPrint: 是否在终端打印日志
        """
        if isPrint:
            self.logger.error(message)
        else:
            # 仅记录到文件，不打印到终端
            for handler in self.logger.handlers:
                if isinstance(handler, logging.FileHandler) and ("Error" in handler.baseFilename or "All" in handler.baseFilename):
                    handler.emit(logging.LogRecord(
                        name=self.logger.name,
                        level=logging.ERROR,
                        pathname=__file__,
                        lineno=0,
                        msg=message,
                        args=None,
                        exc_info=None
                    ))

    def warning(self, message, isPrint=True):
        """
        记录 WARNING 级别的日志
        :param message: 日志信息
        :param isPrint: 是否在终端打印日志
        """
        if isPrint:
            self.logger.warning(message)
        else:
            # 仅记录到文件，不打印到终端
            for handler in self.logger.handlers:
                if isinstance(handler, logging.FileHandler) and ("Warning" in handler.baseFilename or "All" in handler.baseFilename):
                    handler.emit(logging.LogRecord(
                        name=self.logger.name,
                        level=logging.WARNING,
                        pathname=__file__,
                        lineno=0,
                        msg=message,
                        args=None,
                        exc_info=None
                    ))

    def device_log(self, message, device_name=None, isPrint=True):
        """
        记录设备交互日志
        :param message: 日志信息
        :param device_name: 设备名称
        :param isPrint: 是否在终端打印日志
        """
        log_message = f"[Device] [Name: {device_name}] {message}" if device_name else f"[Device] {message}"
        if isPrint:
            self.logger.info(log_message)
        else:
            # 仅记录到文件，不打印到终端
            for handler in self.logger.handlers:
                if isinstance(handler, logging.FileHandler) and ("Info" in handler.baseFilename or "All" in handler.baseFilename):
                    handler.emit(logging.LogRecord(
                        name=self.logger.name,
                        level=logging.INFO,
                        pathname=__file__,
                        lineno=0,
                        msg=log_message,
                        args=None,
                        exc_info=None
                    ))

    def tcp_log(self, message, ip=None, isPrint=True):
        """
        记录 TCP 交互日志
        :param message: 日志信息
        :param ip: 客户端 IP 地址
        :param isPrint: 是否在终端打印日志
        """
        log_message = f"[TCP] [IP: {ip}] {message}" if ip else f"[TCP] {message}"
        if isPrint:
            self.logger.info(log_message)
        else:
            # 仅记录到文件，不打印到终端
            for handler in self.logger.handlers:
                if isinstance(handler, logging.FileHandler) and ("Info" in handler.baseFilename or "All" in handler.baseFilename):
                    handler.emit(logging.LogRecord(
                        name=self.logger.name,
                        level=logging.INFO,
                        pathname=__file__,
                        lineno=0,
                        msg=log_message,
                        args=None,
                        exc_info=None
                    ))